bpo-9303: Migrate sqlite3 module to _v2 API to enhance performance#359
Conversation
berkerpeksag
left a comment
There was a problem hiding this comment.
I think we can also avoid calling sqlite3_reset in _pysqlite_seterror if the v2 API is available.
|
I haven't checked yet, but I also think that the check for cpython/Modules/_sqlite/cursor.c Line 553 in c92e604 |
| Py_BEGIN_ALLOW_THREADS | ||
| #ifdef HAVE_SQLITE3_OPEN_V2 | ||
| rc = sqlite3_open_v2(database, &self->db, | ||
| SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); |
There was a problem hiding this comment.
Style nitpick: FOO|BAR is more common than FOO | BAR in sqlite3 code base.
| } | ||
| Py_BEGIN_ALLOW_THREADS | ||
| #ifdef HAVE_SQLITE3_OPEN_V2 | ||
| rc = sqlite3_open_v2(database, &self->db, |
There was a problem hiding this comment.
I think that there is an opportunity to simplify this whole SQLITE_OPEN_URI and HAVE_SQLITE3_OPEN_V2 dance.
(The use of Py_BEGIN_ALLOW_THREADS is a bit weird in line 111 and line 120.)
done
I don't think we should do this because we can get |
berkerpeksag
left a comment
There was a problem hiding this comment.
This looks pretty good to me. We just need an entry in Misc/NEWS (please add "Patch by Aviv Palivoda." too)
| (void)sqlite3_reset(st); | ||
| } | ||
| #endif | ||
|
|
There was a problem hiding this comment.
Nitpick: Please remove extra empty line.
| } | ||
| Py_BEGIN_ALLOW_THREADS | ||
| /* No need to use sqlite3_open_v2 as sqlite3_open(filename, db) is the | ||
| same as sqlite3_open_v2(filename, db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)*/ |
There was a problem hiding this comment.
Nitpick: FOO|BAR syntax instead of FOO | BAR.
Also, finish the line with a full stop and space:
/* [...] NULL). */
Right, we can still get |
|
I have removed the reset but I left the recompile because we should recompile before calling sqlite3_step again. |
| int errorcode; | ||
|
|
||
| /* SQLite often doesn't report anything useful, unless you reset the statement first */ | ||
| #if SQLITE_VERSION_NUMBER >= 3003009 |
serhiy-storchaka
left a comment
There was a problem hiding this comment.
Fix an error found by @berkerpeksag.
berkerpeksag
left a comment
There was a problem hiding this comment.
Thanks, Aviv! I will wait for Serhiy's approval and merge this.
Converts 12 BasicBlock-related extern "C" wrapper functions in
lir_c_api.cpp to static inline definitions in lir_c_api.h. Each wrapper
was a thin reinterpret_cast + field access; layout-pin static_asserts
in lir_instr_c_verify.cpp guarantee LirBasicBlock (C) and BasicBlock
(C++) field offsets match, making direct field access via cast safe
across both languages.
Files:
M Python/jit/lir/lir_c_api.h +82 / -19 (12 static inline defs added)
M Python/jit/lir/lir_c_api.cpp +6 / -68 (12 wrapper bodies removed)
Net: -75 / +81 = +6 LOC (header inline definitions slightly larger than
collapsed C++ bodies due to per-function comment + cast pattern).
Inlined functions (all static inline in lir_c_api.h):
jit_lir_block_num_preds -> ((const LirBasicBlock*)b)->num_preds_
jit_lir_block_get_pred -> ((const LirBasicBlock*)b)->predecessors_[i]
jit_lir_block_num_succs -> ((const LirBasicBlock*)b)->num_succs_
jit_lir_block_get_succ -> ((const LirBasicBlock*)b)->successors_[i]
jit_lir_block_get_last_instr -> ((const LirBasicBlock*)b)->instr_tail_
jit_lir_block_get_first_instr -> ((const LirBasicBlock*)b)->instr_head_
jit_lir_block_num_instrs -> ((const LirBasicBlock*)b)->num_instrs_
jit_lir_block_get_false_succ -> ((const LirBasicBlock*)b)->successors_[1]
jit_lir_block_get_section -> (int)((const LirBasicBlock*)b)->section_
jit_lir_block_set_section -> ((LirBasicBlock*)b)->section_ = ...
jit_lir_block_get_id -> ((const LirBasicBlock*)b)->id_
jit_lir_block_get_instr_at -> linked-list traversal via instr_head_/next_
Caller audit (preserved by header-inline):
cold_block_marker.c: 14 sites
dce.c: 4 sites
blocksorter.c: 4 sites
printer_c.c: 11 sites
verify.c: 1 site
TOTAL: 34 caller sites, ALL preserved by inline (same function names,
same signatures, same return semantics).
Behavior preservation:
- Field offsets: guaranteed by static_asserts in lir_instr_c_verify.cpp
(specifically: id_, successors_, instr_head_, section_ offsets all
cross-validated)
- num_succs_ / num_preds_ : direct field reads vs C++ predecessors().size()
— C++ BlockSpan::size() returns the same num_preds_ field (block.h:24)
- get_false_succ : preserves original no-bounds-check semantic
(original used successors_[1] without check; matches inline version)
- set_section : original called BasicBlock::setSection() which is just
section_ = section (block.h:183 confirmed); inline writes field directly
- get_instr_at : C inline traverses instr_head_->next_ chain identically
to C++ instructions().front() + cur->next_ loop
.h-decl <-> .cpp-defn enumeration: COMPREHENSIVE (per c4 lesson).
All 12 extern declarations in lir_c_api.h:40-51 mapped to definitions
in lir_c_api.cpp:63-129; all 12 inlined; 0 missed; 0 dead methods to
delete this round (all 12 have active callers per audit above).
.h-inline <-> decl-visibility check: lir_c_api.h is self-contained for
the inlined functions — uses LirBasicBlock + LirInstruction (declared
in lir_types_c.h, included by lir_c_api.h:15) + JitLirBlock/JitLirInstr
typedefs (defined later in same file). LirCodeSection used in
set_section is also from lir_types_c.h. No new include needed.
PRE-COMMIT BUILD VERIFIED (per supervisor 16:12:20Z compile-before-commit
directive, first real test of the workflow per pythia python#359):
Build command:
cd Python/jit_build/build && cmake --build . --target jit -j 16
(then) cd cpython && make -j16 python
Build trailer (verbatim, x86_64, 2026-05-12):
[ 24%] Linking CXX static library libjit.a
[100%] Built target jit
clang++ ... -o python ... -Wl,--start-group Python/jit_build/build/libjit.a ...
(link successful, exit 0)
Warnings: 5 pre-existing (block-comment in reader_c.h:22, unused-private-
field in phoenix_asm_wrapper.h:865 etc.); ZERO new warnings introduced.
Binary post-build:
stat: 2026-05-12 10:03:36 python
sys.version: 3.12.13 (heads/phoenix-asm-integration:6aedfa8d1e, ...)
NOTE: version string reports c5 (6aedfa8) because git HEAD at
compile-time was c5; binary CONTAINS the c6 inline code (in libjit.a)
but the embedded commit-string lags by one commit. Testkeeper Tier 1
rebuild post-c6-commit will produce a binary with c6 commit string.
Working tree clean post-build (verified: only the 2 staged c6 files M).
Pre-ARM64 APPROVE pending; ABBA waived (inline conversion of byte-equivalent
field accessors, no executable-path semantic change beyond removed function-
call overhead which the optimizer would have eliminated anyway via LTO).
Use the _v2 API when possible.